home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_05 / cmenu13.exe / CMENU2.C < prev    next >
C/C++ Source or Header  |  1992-04-06  |  14KB  |  611 lines

  1. /************************************************************
  2.  *    Program: CMENU Menu Compiler
  3.  *  Module: cmenu2.c    
  4.  *        Menu Compiler:
  5.  *        Menu/Item Token Processing Functions
  6.  *    Written by: Leor Zolman, 7/91
  7.  ************************************************************/
  8.  
  9. #include "cmenu.h"
  10. #include "ccmenu.h"
  11.  
  12. #if __STDC__
  13. #pragma hdrstop
  14. #endif
  15.  
  16. #include <ctype.h>
  17.  
  18.  
  19. /************************************************************
  20.  * do_menu():
  21.  *    Process the MENU keyword
  22.  ************************************************************/
  23.  
  24. int do_menu()
  25. {
  26.     int tok;
  27.  
  28.     if (in_menu)        /* Are we currently processing a menu?    */
  29.     {                    /* yes.                                    */
  30.         warning("Endmenu missing from previous menu");
  31.         do_endmenu();    /* give them the benefit of the doubt    */
  32.     }
  33.  
  34.     if ((tok = gettok()) != T_STRING)
  35.     {
  36.         if (n_menus)
  37.             error("Menu name missing; menu unreachable");
  38.         sprintf(tparam, "menu%d", n_menus + 1);    /* force a name        */
  39.         ungettok(tok);
  40.     }
  41.     
  42.     if (strlen(tparam) > MAX_NAME)
  43.     {
  44.         error("The name '%s' is too long (%d chars max)",
  45.                 tparam, MAX_NAME);
  46.         tparam[MAX_NAME] = '\0';                /* truncate name    */
  47.     }
  48.     
  49.     if ((MIp = find_menu(tparam)) == NULL)        /* menu exist?        */
  50.     {
  51.         MInfo[n_menus] = create_menu(tparam);    /* no.                */
  52.         if (fatal)
  53.             return ERROR;                        /* creation error    */
  54.         else
  55.             MIp = &MInfo[n_menus++];            /* OK, bump count    */
  56.     }
  57.     else
  58.         if (MIp -> Processed)                    /* redefinition?    */
  59.             return fatalerr("Duplicate Menu definition"); /* yes.    */
  60.         
  61.     Mp = &MIp -> Menu;
  62.     *Mp->title = *Mp->path = '\0';
  63.     Mp->nitems = Mp->widest = 0;
  64.     Mp->spacing = Mp->columns = Mp->escape = DEFAULT;
  65.     Mp->align = DEFAULT;
  66.  
  67.     in_item = FALSE;            /* state variables describing the    */    
  68.     in_menu = TRUE;                /* current menu being processed        */
  69.     n_items = 0;                
  70.     n_refs = 0;                    /* no forward item references yet    */
  71.  
  72.     if ((tok = gettok()) != T_COLON)            /* optional colon    */
  73.         ungettok(tok);
  74.     
  75.     return OK;
  76. }
  77.  
  78.  
  79. /************************************************************
  80.  * do_title():
  81.  *    Process the TITLE clause for a menu.
  82.  ************************************************************/
  83.  
  84. int do_title()
  85. {
  86.     int tok;
  87.  
  88.     if ((tok = gettok()) != T_STRING)
  89.     {
  90.         error("Title text missing");
  91.         ungettok(tok);
  92.     }
  93.         
  94.     if (!in_item)            /* Before all items?        */
  95.     {                        /* yes.                        */
  96.         if (*Mp->title)
  97.             return error("A Menu Title has already been specified");
  98.         if (strlen(tparam) > MAX_TXTWID - 1)
  99.             return error("Menu Title is too long (max %d chars)",
  100.                     MAX_TXTWID-1);
  101.         strcpy(Mp->title, tparam);
  102.     }
  103.     else
  104.         return error("The Menu Title must precede all Menu Items.");
  105.  
  106.     return OK;
  107. }
  108.  
  109.  
  110. /************************************************************
  111.  * do_path():
  112.  *    Process the PATH option.
  113.  *    Note that the PATH option may apply to an entire
  114.  *    menu or just to a single menu item (determined
  115.  *    by context.)
  116.  ************************************************************/
  117.  
  118. int do_path()
  119. {
  120.     int tok;
  121.     char c, *cp;
  122.     
  123.     if ((tok = gettok()) != T_STRING)
  124.     {
  125.         error("Path text missing");
  126.         ungettok(tok);
  127.     }
  128.         
  129.     if ((c = tparam[strlen(tparam) - 1]) == '/' || c == '\\')    /* delete */
  130.         tparam[strlen(tparam) - 1] = '\0';                /* traling slash  */
  131.  
  132.     if (strlen(tparam) > MAX_PATH - 1)
  133.         return error("The specified path is too long (max %d chars)",
  134.                 MAX_PATH - 1);
  135.  
  136.     if (!in_item)            /* Referring to the menu?    */
  137.     {                        /* yes.                        */
  138.         if (*Mp->path)
  139.             return error("A Menu Path has already been specified");
  140.         strcpy(Mp->path, tparam);
  141.     }
  142.     else
  143.     {                        /* Must be for the item.    */
  144.         if (*Ip->path)
  145.             return error("An Item Path has already been specified");
  146.         strcpy(Ip->path, tparam);
  147.     }
  148.     return OK;
  149. }
  150.  
  151.  
  152. /************************************************************
  153.  * do_align():
  154.  *    Process text alignment option.
  155.  *  Note: this option is a no-op. I decided there wasn't
  156.  *    any real need for any other than left-justified item
  157.  *    alignment. But, in case anyone thinks of a use for it,
  158.  *    I'm leaving in the ability to process the option.
  159.  ************************************************************/
  160.  
  161. int do_align()
  162. {
  163.     int tok;
  164.     
  165.     if (in_item)
  166.         return error("The Align clause must precede all Menu Items.");
  167.  
  168.     if (Mp->align)
  169.         return error("Align option already specified for this menu");
  170.     
  171.     switch (tok = gettok())
  172.     {
  173.         case T_LEFT:
  174.             Mp->align = 'L'; 
  175.             break;
  176.             
  177.         case T_RIGHT:
  178.             Mp->align = 'R';
  179.             break;
  180.             
  181.         case T_CENTER:
  182.             Mp->align = 'C';
  183.             break;
  184.             
  185.         default:
  186.             ungettok(tok);
  187.             return error("Align missing valid modifier");
  188.     }
  189.     return OK;
  190. }
  191.  
  192.  
  193. /************************************************************
  194.  * do_spacing():
  195.  *    Process the SPACING option (applies
  196.  *    to menus only.)
  197.  ************************************************************/
  198.  
  199. int do_spacing()
  200. {
  201.     int tok;
  202.  
  203.     if ((tok = gettok()) != T_VALUE)
  204.     {
  205.         error("Spacing value missing");
  206.         ungettok(tok);
  207.     }
  208.  
  209.     if (in_item)
  210.         return error("Spacing option must precede all menu items");
  211.  
  212.     if (Mp->spacing)
  213.         return error("Spacing option already specified");
  214.  
  215.              /* only single and double spacing supported    */
  216.     if (vparam != 1 && vparam != 2)
  217.         return error("Spacing value must be either 1 or 2");
  218.  
  219.     Mp->spacing = vparam;
  220.     return OK;
  221. }
  222.  
  223.  
  224. /************************************************************
  225.  * do_columns():
  226.  *    Process the COLUMNS option
  227.  ************************************************************/
  228.  
  229. int do_columns()
  230. {
  231.     int tok;
  232.     
  233.     if ((tok = gettok()) != T_VALUE)
  234.     {
  235.         error("Columns value missing");
  236.         ungettok(tok);
  237.     }
  238.  
  239.     if (in_item)
  240.         return error("Columns option must precede all menu items");
  241.  
  242.     if (Mp->columns)
  243.         return error("Columns option already specified");
  244.  
  245.     if (vparam < 1 || vparam > 6)    /*  6 seems a reasonable max. */
  246.         return error("Columns value must be between 1 and 6");
  247.     Mp->columns = vparam;
  248.     return OK;
  249. }
  250.  
  251.  
  252. /************************************************************
  253.  * do_escape():
  254.  *    Process "escape" and "noescape" menu options
  255.  ************************************************************/
  256.  
  257. int do_escape()
  258. {
  259.     if (in_item)
  260.         return error("\"%s\" must appear before all menu items",
  261.             keywords[token].keyword);
  262.     
  263.     if (Mp->escape)
  264.         return error("Escape option already specified");
  265.     Mp->escape = (token == T_ESCAPE) ? YES : NO;
  266.  
  267.     return OK;
  268. }
  269.  
  270.  
  271. /************************************************************
  272.  * do_endmenu():
  273.  *    Process ENDMENU keyword
  274.  ************************************************************/
  275.  
  276. int do_endmenu()
  277. {
  278.     int i;
  279.     
  280.     if (!n_items)
  281.         error("No menu items specified for this menu");
  282.     
  283.     for (i = 0; i < n_refs; i++)        /* check for unresolved        */
  284.     {                                    /* forward Item references    */
  285.         if (*fwd_refs[i].refp == UNDEF_FWD)
  286.         {
  287.             int save_lineno = lineno;
  288.             lineno = fwd_refs[i].lineno;
  289.             error("Unresolved reference to Item \"%s\"",
  290.                 fwd_refs[i].iname);
  291.             lineno = save_lineno;
  292.         }
  293.     }
  294.     
  295.     in_menu = in_item = FALSE;            /* done with current menu    */
  296.     MIp -> Processed = TRUE;            /* it is now processed        */
  297.     Mp -> nitems = n_items;
  298.     return OK;
  299. }
  300.  
  301.  
  302. /************************************************************
  303.  * do_item():
  304.  *    Process the ITEM clause. Create a new ite
  305.  *    and fill in any existing forward references to it.
  306.  ************************************************************/
  307.  
  308. int do_item()
  309. {
  310.     int tok, i;
  311.     char *cp, c;
  312.     
  313.     if (n_items)
  314.         itemcheck();    /* check for previous item's completion */
  315.  
  316.     if ((tok = gettok()) != T_STRING)    /* label specified?        */
  317.     {                                    /* If not, stuff unique    */
  318.         sprintf(tparam,"dummy!%d", n_items);  /* dummy name in    */    
  319.             ungettok(tok);
  320.     }
  321.     else
  322.     {
  323.         if (strlen(tparam) > MAX_NAME)
  324.         {
  325.             error("Item name \"%s\" too long. Max %d chars.",
  326.                         tparam, MAX_NAME);
  327.             tparam[MAX_NAME] = '\0';
  328.         }
  329.         else for (cp = tparam; c = *cp; cp++)
  330.             if (!(isalpha(c) || isdigit(c) || c == '_'))
  331.             {
  332.                 error("Invalid char in identifier name: \"%s\"",
  333.                             tparam);
  334.                 *cp = '\0';
  335.                 break;
  336.             }
  337.     }
  338.     
  339.     if ((IIp = find_item(tparam)) != NULL)    /* Item name found?    */
  340.         return error("